﻿namespace RS.CmeFastHandler
{
	using System;
	using System.Configuration;
	using System.Net;
	using System.Net.Sockets;
	using System.Threading;

	using Tigera.LibCommon;

	public class Listener
	{


		private ConnectionInfo address = null;
		private SharedQueue<byte[]> queue = new SharedQueue<byte[]>();
		private Thread thread;
		private string threadName;

		//private Thread secondThread;
		EventWaitHandle waitHandler;





		public Listener(string threadName, ConnectionInfo address, EventWaitHandle handle)
		{
			this.threadName = threadName;
			if (this.address == null)
			{
				this.address = address;
			}
			this.waitHandler = handle;
		}



		#region Properties

		public SharedQueue<byte[]> UdpQueue
		{
			get
			{
				return this.queue;
			}
			set
			{
				this.queue = value;
			}
		}

		#endregion Properties



		public void Start()
		{
			lock (this)
			{
				if (address.UdpA_Port == address.UdpB_Port)
				{
					this.thread = new Thread(new ThreadStart(this.ReceiveBothData));
					this.thread.IsBackground = true;
					this.thread.Name = this.threadName;	// +FEED.A_AND_B;
					this.thread.Start();
				}
				else
				{
					// 因为带参数，所以用一下方式调用线程。
					WaitCallback callback = new WaitCallback(this.ReceiveData);
					Param p = new Param() { ip = address.UdpA, port = address.UdpA_Port };
					ThreadPool.QueueUserWorkItem(callback, p);

					Param p2 = new Param() { ip = address.UdpB, port = address.UdpB_Port };
					ThreadPool.QueueUserWorkItem(callback, p2);
				}
			}
		}

		private void ClearQueue()
		{
			this.queue.Clear();
		}

		private void ReceiveBothData()
		{
			lock (this)
			{
				try
				{

					UdpClient socket = new UdpClient(address.UdpA_Port);
					if (address != null)
					{
						System.Net.IPAddress addr;

						if (address.UdpA != null && (addr = IPAddress.Parse(address.UdpA)) != null)
						{
							socket.JoinMulticastGroup(addr, IPAddress.Parse(ConfigurationManager.AppSettings["CMELocalIPAddress"].ToString()));
						}
						if (address.UdpB != null && (addr = IPAddress.Parse(address.UdpB)) != null)
						{
							socket.JoinMulticastGroup(addr, IPAddress.Parse(ConfigurationManager.AppSettings["CMELocalIPAddress"].ToString()));
						}

						IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0);
						while (waitHandler.WaitOne(0, false))
						{
							byte[] data = socket.Receive(ref iep);
							this.queue.Enqueue(data);
						}
						socket.Close();
					}

				}
				catch (Exception e)
				{
					TiTracer.TraceDebug(e.ToString());

				}
			}
		}

		private void ReceiveData(object param)
		{
			Param p = (Param)param;
			string ip = p.ip;
			int port = p.port;
			lock (this)
			{
				try
				{

					UdpClient socket = new UdpClient(port);
					socket.JoinMulticastGroup(IPAddress.Parse(ip), IPAddress.Parse(ConfigurationManager.AppSettings["CMELocalIPAddress"].ToString()));
					IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0);
					while (waitHandler.WaitOne(0, false))
					{
						byte[] data = socket.Receive(ref iep);
						this.queue.Enqueue(data);
					}
					socket.Close();
				}
				catch (Exception e)
				{
					TiTracer.TraceDebug(e.ToString());
				}
			}
		}



		#region Nested Types

		struct Param
		{


			public string ip;
			public int port;


		}

		#endregion Nested Types
	}
}